package com.example.factory;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.example.domain.dto.result.*;
import com.example.domain.entity.*;
import com.example.mapper.DeptMapper;

import java.time.LocalDate;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;

import com.example.mapper.MaterialMapper;
import com.example.mapper.PersonMapper;
import com.example.mapper.ProviderMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ResultFactory {
    @Autowired
    private DeptMapper deptMapper;

    @Autowired
    private PersonMapper personMapper;

    @Autowired
    private ProviderMapper providerMapper;

    @Autowired
    private MaterialMapper materialMapper;

    public PersonResult convert(Person person) {
        PersonResult result = new PersonResult();
        BeanUtils.copyProperties(person, result);
        Integer deptId = person.getDeptId();
        if (deptId != null) {
            result.setDeptName(deptMapper.getDeptName(deptId));
        }
        return result;
    }

    public RepairResult convert(Repair repair) {
        RepairResult result = new RepairResult();
        BeanUtils.copyProperties(repair, result);
        Integer deptId = repair.getDeptId();
        if (deptId != null) {
            result.setDeptName(deptMapper.getDeptName(deptId));
        }
        return result;
    }

    public ScheduleResult convert(Schedule schedule) {
        ScheduleResult result = new ScheduleResult();
        BeanUtils.copyProperties(schedule, result);
        Integer deptId = schedule.getDeptId();
        Integer personId = schedule.getPersonId();
        Integer substitutePersonId = schedule.getSubstitutePersonId();
        if (deptId != null) {
            result.setDeptName(deptMapper.getDeptName(deptId));
        }
        if(personId != null) {
            result.setPersonName(personMapper.getPersonName(personId));
        }
        if(substitutePersonId != null) {
            result.setSubstitutePersonName(personMapper.getPersonName(personId));
        }
        return result;
    }

    public ProductionPlanResult convert(ProductionPlan plan) {
        ProductionPlanResult result = new ProductionPlanResult();
        BeanUtils.copyProperties(plan, result);
        Integer deptId = plan.getDeptId();
        if (deptId != null) {
            result.setDeptName(deptMapper.getDeptName(deptId));
        }
        return result;
    }

    // 将schedule列表转换为ScheduleResult
    // schedules为查询到的排班列表，range为日期范围(day为当天， week为一周，month为一月), date为查询的时间
    // date不是范围的起始日期，返回的是date所在的当周或当月
    public ScheduleList scheduleList(List<Schedule> schedules, String range, LocalDate date) {
        ScheduleList result = new ScheduleList();
        result.setRange(range);
        List<ScheduleResult> scheduleResults = schedules.stream().map(this::convert).toList();

        // 确定日期范围
        LocalDate beginDate, endDate;
        switch (range) {
            case "day":
                beginDate = date;
                endDate = date;
                break;
            case "week":
                beginDate = date.minusDays(date.getDayOfWeek().getValue() - 1);
                endDate = beginDate.plusDays(6);
                break;
            case "month":
                beginDate = date.withDayOfMonth(1);
                endDate = date.withDayOfMonth(date.lengthOfMonth());
                break;
            default:
                throw new IllegalArgumentException("Invalid range: " + range);
        }
        result.setBeginDate(beginDate);
        result.setEnDate(endDate);

        // 按日期分组并排序
        List<List<ScheduleResult>> schedulesByDate = new ArrayList<>();
        for (LocalDate currentDate = beginDate; !currentDate.isAfter(endDate); currentDate = currentDate.plusDays(1)) {
            final LocalDate d = currentDate;
            List<ScheduleResult> daySchedules = scheduleResults.stream()
                    .filter(s -> s.getDate().equals(d))
                    .sorted((s1, s2) -> {
                        // 按班次（早中晚）排序
                        String[] shifts = {"早", "中", "晚"};
                        return Arrays.asList(shifts).indexOf(s1.getShift()) -
                                Arrays.asList(shifts).indexOf(s2.getShift());
                    })
                    .collect(Collectors.toList());
            schedulesByDate.add(daySchedules);
        }
        result.setSchedules(schedulesByDate);

        // 设置部门名称（如果有）
        if (!schedules.isEmpty()) {
            Integer deptId = schedules.get(0).getDeptId();
            if (deptId != null) {
                result.setDeptName(deptMapper.getDeptName(deptId));
            }
        }

        return result;
    }

    public IPage<PersonResult> convertPersonPage(IPage<Person> page) {
        return new Page<PersonResult>(page.getCurrent(), page.getSize(), page.getTotal())
            .setRecords(page.getRecords().stream().map(this::convert).toList());
    }

    public IPage<RepairResult> convertRepairPage(IPage<Repair> page) {
        return new Page<RepairResult>(page.getCurrent(), page.getSize(), page.getTotal())
            .setRecords(page.getRecords().stream().map(this::convert).toList());
    }

    public IPage<ScheduleResult> convertSchedulePage(IPage<Schedule> page) {
        return new Page<ScheduleResult>(page.getCurrent(), page.getSize(), page.getTotal())
            .setRecords(page.getRecords().stream().map(this::convert).toList());
    }

    public IPage<ProductionPlanResult> convertProductionPlanPage(IPage<ProductionPlan> page) {
        return new Page<ProductionPlanResult>(page.getCurrent(), page.getSize(), page.getTotal())
            .setRecords(page.getRecords().stream().map(this::convert).toList());
    }

    public ProductResult convert(Product product) {
        ProductResult result = new ProductResult();
        BeanUtils.copyProperties(product, result);
        Integer deptId = product.getWorkshopId();
        if (deptId != null) {
            result.setWorkshopName(deptMapper.getDeptName(deptId));
        }
        return result;
    }

    public IPage<ProductResult> convertProductPage(IPage<Product> page) {
        return new Page<ProductResult>(page.getCurrent(), page.getSize(), page.getTotal())
            .setRecords(page.getRecords().stream().map(this::convert).toList());
    }

    public MaterialPurchaseResult convert(MaterialPurchase materialPurchase) {
        MaterialPurchaseResult result = new MaterialPurchaseResult();
        BeanUtils.copyProperties(materialPurchase, result);

        result.setPersonName(this.personMapper.getPersonName(materialPurchase.getPersonId()));
        result.setDeptName(this.deptMapper.getDeptName(materialPurchase.getDeptId()));
        result.setProviderName(providerMapper.getProviderName(materialPurchase.getProviderId()));
        result.setPurchaserName(personMapper.getPersonName(materialPurchase.getPersonId()));
        return result;
    }

    public IPage<MaterialPurchaseResult> convertMaterialPurchasePage(IPage<MaterialPurchase> page) {
        return new Page<MaterialPurchaseResult>(page.getCurrent(), page.getSize(), page.getTotal())
            .setRecords(page.getRecords().stream().map(this::convert).toList());
    }
}
